package com.naiterui.ehp.bs.ds.modules.security.service;

import com.naiterui.ehp.bp.security.exception.AuthenticationException;
import com.naiterui.ehp.bp.support.exception.BusinessException;
import com.naiterui.ehp.bp.utils.context.SpringContextHolder;
import com.naiterui.ehp.bs.ds.common.constants.CacheConstants;
import com.naiterui.ehp.bs.ds.common.utils.Constant;
import com.naiterui.ehp.bs.ds.common.utils.JwtUser;
import com.naiterui.ehp.bs.ds.modules.sys.entity.Role;
import com.naiterui.ehp.bs.ds.modules.sys.entity.User;
import com.naiterui.ehp.bs.ds.modules.sys.service.IUserService;
import java.util.List;
import java.util.stream.Collectors;
import lombok.extern.slf4j.Slf4j;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.lang.NonNull;
import org.springframework.security.core.authority.SimpleGrantedAuthority;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.security.core.userdetails.UserDetailsService;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

@Slf4j
@Service
public class JwtUserDetailsServiceImpl implements UserDetailsService {

  @Override
  @Cacheable(value = CacheConstants.USER, key = "#username")
  @Transactional(readOnly = true, rollbackFor = Exception.class)
  public UserDetails loadUserByUsername(@NonNull String username) {
    User user;
    try {
      user = SpringContextHolder.getBean(IUserService.class).loadUserByUsername(username);
    } catch (BusinessException e) {
      throw new AuthenticationException(e.getMessage(), e);
    }
    List<Role> roles = user.getRoles();
    return JwtUser.builder()
        .id(user.getId())
        .username(user.getUsername())
        .name(user.getName())
        .password(user.getPassword())
        .avatar("")
        .email(user.getEmail())
        .mobile(user.getMobile())
        .deptName(user.getDeptName())
        .roleIdList(user.getRoleIdList())
        .permissions(user.getPermissions())
        .admin(user.getRoleIdList().contains(Constant.SUPER_ADMIN))
        .authorities(roles.stream().map(r -> new SimpleGrantedAuthority(r.getRoleName())).collect(Collectors.toSet()))
        .enabled(user.getStatus() != 0)
        .lastPasswordResetDate(user.getLastPasswordResetDate())
        .warehouseId(user.getWarehouseId())
        .createdAt(user.getCreatedAt())
        .build();
  }
}
